package com.ominext.camera;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.media.ExifInterface;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.ominext.beautifulcapture.R;
import com.ominext.home.HomeActivity;
import com.ominext.home.Path;
import com.ominext.utils.DeviceUtils;
import com.ominext.utils.ImageUtils;

public class CustomCameraActivity extends Activity implements OnTouchListener {

	int idViewFrame = 0, idViewIcon = 0, saveFrame = 0;
	private static final int TAG = 1000;
	int[] tagArr = new int[100];
	Integer idTag = TAG;
	boolean previewing = false, isPicTaken = false;
	final static String DEBUG_TAG = "CustomCameraActivity";

	// hideView default Invisible, when click frameButton, it'll be visible
	View hideViewFrame;
	View hideViewIcon;

	Camera camera;

	// ImageView show the picture just captured
	ImageView frameView;

	// Where we preview the Camera
	CameraPreview preview;

	// ImageView show Icon, we can drag + drop
	ImageView _image;

	// Area, where we can drag + drop
	ViewGroup _root;
	ImageButton _button;

	private int _xDelta;
	private int _yDelta;

	// Id of current Camera
	Camera.CameraInfo currentCameraId = new Camera.CameraInfo();

	// frameLayout is the child of the HorizontalScrollView ...
	private LinearLayout frameLayout, iconLayout;
	private View cell;

	// Inflate item.xml to iconView to show the Icon with a button
	private View iconView;

	// this is arrays that holds the IDs of the drawables ...
	private int[] frames = { R.drawable.none, R.drawable.khung_hinh_dep_1,
			R.drawable.khung_hinh_dep_2, R.drawable.khung_hinh_dep_3,
			R.drawable.khung_hinh_dep_4, R.drawable.khung_hinh_dep_5 };
	private int[] icons = { R.drawable.dd1, R.drawable.dd2, R.drawable.dd3,
			R.drawable.dd4, R.drawable.dd5, R.drawable.dd6, R.drawable.dd7 };

	private Button captureButton, switchButton, frameButton, iconButton,
			backButton;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		// Remove title bar
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);

		// Remove notification bar
		this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// Set the Orientation: PORTRAIT
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

		captureButton = (Button) findViewById(R.id.button_capture);
		switchButton = (Button) findViewById(R.id.button_switch);
		frameButton = (Button) findViewById(R.id.button_showframe);
		iconButton = (Button) findViewById(R.id.button_showicon);
		backButton = (Button) findViewById(R.id.button_back);

		frameView = (ImageView) findViewById(R.id.frame_view);
		hideViewFrame = (View) findViewById(R.id.hideView_frame);
		hideViewIcon = (View) findViewById(R.id.hideView_icon);
		_root = (ViewGroup) findViewById(R.id.camArea);
		ImageButton previewBtn = (ImageButton) findViewById(R.id.button_img);

		backButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent a = new Intent(getApplicationContext(),
						HomeActivity.class);
				a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
				startActivity(a);
			}
		});

		previewBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub

			}
		});

		frameView.setClickable(true);
		frameView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub

				captureButton.setEnabled(false);
				camera.autoFocus(myAutoFocusCallback);

				hideViewIcon.setVisibility(View.INVISIBLE);
				idViewIcon = 0;
				hideViewFrame.setVisibility(View.INVISIBLE);
				idViewFrame = 0;

				for (int i = 2; i < _root.getChildCount(); ++i) {
					View nextChild = _root.getChildAt(i);
					((RelativeLayout) nextChild).getChildAt(1).setVisibility(
							View.INVISIBLE);
					((RelativeLayout) nextChild).getChildAt(2).setVisibility(
							View.INVISIBLE);
				}
			}
		});

		/************* ADD FRAME *************/

		frameLayout = (LinearLayout) findViewById(R.id.linearLayout_frame);
		/*
		 * Loop all Images inflate @cell into an Element Set Listen for per
		 * Element
		 */
		for (int i = 0; i < frames.length; i++) {
			final int x = i;
			cell = getLayoutInflater().inflate(R.layout.cell, null);

			final ImageView imageView = (ImageView) cell
					.findViewById(R.id._image);
			imageView.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					if (x == 0) {
						frameView.setBackgroundResource(0);
						hideViewFrame.setVisibility(View.INVISIBLE);
						idViewFrame = 0;
						saveFrame = 0;
					} else {
						frameView.setBackgroundResource(frames[x]);
						hideViewFrame.setVisibility(View.INVISIBLE);
						idViewFrame = 0;
						saveFrame = frames[x];
					}
				}
			});
			imageView.setImageResource(frames[i]);
			// add view to ScrollView
			frameLayout.addView(cell);
		}

		/************* ADD ICON *************/

		iconLayout = (LinearLayout) findViewById(R.id.linearLayout_icon);
		/*
		 * Loop all Images inflate @cell into an Element Set Listen for per
		 * Element
		 */
		for (int i = 0; i < icons.length; i++) {
			final int x = i;
			cell = getLayoutInflater().inflate(R.layout.cell, null);

			final ImageView imageView = (ImageView) cell
					.findViewById(R.id._image);
			imageView.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
							200, 200);
					layoutParams.leftMargin = 10;
					layoutParams.topMargin = 10;
					layoutParams.bottomMargin = -100;
					layoutParams.rightMargin = -100;

					iconView = getLayoutInflater().inflate(R.layout.item,
							_root, false);

					_image = (ImageView) iconView.findViewById(R.id._img);
					_button = (ImageButton) iconView.findViewById(R.id._imgbtn);

					// Set on touch listener for iconView
					iconView.setOnTouchListener(CustomCameraActivity.this);
					iconView.setClickable(true);

					// Set background for @param:_image belong to iconView
					_image.setBackgroundResource(icons[x]);

					// iconView.setLayoutParams(layoutParams);

					_root.addView(iconView, layoutParams);

					/*
					 * Set Tag for each Child View in ViewGroup
					 * 
					 * @param: tagArr[] is array contain Resource of all
					 * IconView (get from icons[]) Each Icon has been added,
					 * 
					 * @idTag increase 1
					 */
					iconView.setTag(idTag);
					tagArr[idTag - TAG] = icons[x];
					idTag++;
					Log.d("tdTag: ", "" + idTag);

					/*
					 * Set onClickListener for @param:_button After click in
					 * 
					 * @_button, Parent View of this button will be removed
					 */
					_button.setOnClickListener(new OnClickListener() {

						@Override
						public void onClick(View v) {
							// TODO Auto-generated method stub
							Toast.makeText(CustomCameraActivity.this,
									"Clicked", Toast.LENGTH_SHORT).show();
							Log.d("IdTag has been Delete: ",
									"" + ((View) v.getParent()).getTag());
							_root.removeView((View) v.getParent());
						}
					});

					hideViewIcon.setVisibility(View.INVISIBLE);
					idViewIcon = 0;
				}
			});
			imageView.setImageResource(icons[i]);
			// add view to ScrollView
			iconLayout.addView(cell);
		}

		// Listener for button Frame: show list of image
		frameButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				hideViewIcon.setVisibility(View.INVISIBLE);

				if (hideViewFrame.getVisibility() == View.VISIBLE)
					hideViewFrame.setVisibility(View.INVISIBLE);
				else
					hideViewFrame.setVisibility(View.VISIBLE);

				if (idViewFrame == 0) {
					// set color Green
					hideViewFrame.setBackgroundColor(0xFFFFFFFF);
					// set Opacity for view's background
					hideViewFrame.getBackground().setAlpha(50);
					idViewFrame = 1;
				} else {
					idViewFrame = 0;
				}
			}
		});

		// Listener for button Icons: show list of image
		iconButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				hideViewFrame.setVisibility(View.INVISIBLE);

				if (hideViewIcon.getVisibility() == View.VISIBLE)
					hideViewIcon.setVisibility(View.INVISIBLE);
				else
					hideViewIcon.setVisibility(View.VISIBLE);

				if (idViewIcon == 0) {
					// set color Green
					hideViewIcon.setBackgroundColor(0xFFFFFFFF);
					// set Opacity for view's background
					hideViewIcon.getBackground().setAlpha(50);
					idViewIcon = 1;
				} else {
					idViewIcon = 0;
				}
			}
		});

		// Set listen for Capture Button
		captureButton.setOnClickListener(new View.OnClickListener() {

			public void onClick(View v) {
				// TODO Auto-generated method stub
				if (camera != null) {
					//camera.startPreview();
					//camera.takePicture(null, null, pictureCallback);

					new Thread(new Runnable() {

						@Override
						public void run() {
							camera.takePicture(null, null, pictureCallback);
						}
					}).start();

					// camera.startPreview();
					Toast.makeText(getBaseContext(), "Please wait...",
							Toast.LENGTH_SHORT).show();
				}
			}
		});

		/*
		 * Set listen for Switch Button Existence of Front Camera???
		 */
		if (Camera.getNumberOfCameras() == 1) {
			switchButton.setVisibility(View.INVISIBLE);
		} else
			switchButton.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					switchCamera();
					Log.d("Camera", "number " + Camera.getNumberOfCameras());
				}
			});
	}

	/*
	 * AUTO FOCUS
	 */
	AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback() {

		@Override
		public void onAutoFocus(boolean arg0, Camera arg1) {
			// TODO Auto-generated method stub
			captureButton.setEnabled(true);
		}
	};

	/*
	 * SHUTTER SOUND
	 */
	final ShutterCallback shutterCallback = new ShutterCallback() {
		public void onShutter() {
			isPicTaken = true; // set flag true only when shutter is called.
		}
	};

	public void switchCamera() {
		int camBackId = Camera.CameraInfo.CAMERA_FACING_BACK;
		int camFrontId = Camera.CameraInfo.CAMERA_FACING_FRONT;

		if (camera != null) {
			camera.setPreviewCallback(null);
			preview.getHolder().removeCallback(preview);
			camera.stopPreview();
			camera.release();
		}

		// swap the id of the camera to be used
		if (currentCameraId.facing == camBackId) {
			Log.d("SwitchCamIf", "current number " + currentCameraId.facing);
			currentCameraId.facing = camFrontId;// Object CameraInfo to Int
			Log.d("SwitchCamIf", "current number " + currentCameraId.facing);
		} else {
			currentCameraId.facing = camBackId;
			Log.d("SwitchCamEl", "current number " + currentCameraId.facing);
		}
		// Init back Camera
		camera = getCameraInstance(currentCameraId.facing);
		Log.d("SwitchCam", "current number " + currentCameraId.facing);

		/*
		 * Set the true orientation of Camera Then set the preview and start
		 */
		try {
			preview.setCameraDisplayOrientation(currentCameraId.facing, camera);
			camera.setPreviewDisplay(preview.getHolder());
			camera.startPreview();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/*
	 * A safe way to get an instance of the Camera object
	 */
	public static Camera getCameraInstance(int id) {
		Camera c = null;
		try {
			c = Camera.open(id); // attempt to get a Camera instance
		} catch (Exception e) {
			// Camera is not available (in use or does not exist)
		}
		return c; // returns null if camera is unavailable
	}

	/*
	 * Override Func onTouch()
	 */
	@Override
	public boolean onTouch(View view, MotionEvent event) {
		// ImageView v = (ImageView) view;
		// TODO Auto-generated method stub
		final int X = (int) event.getRawX();
		final int Y = (int) event.getRawY();
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view
					.getLayoutParams();
			_xDelta = X - lParams.leftMargin;
			_yDelta = Y - lParams.topMargin;

			/*
			 * Set INVISIBLE all buttons and border in IconView Border has
			 * position 1 in ParrentView Button has position 2 in ParrentView
			 */
			for (int i = 2; i < _root.getChildCount(); ++i) {
				View nextChild = _root.getChildAt(i);
				((RelativeLayout) nextChild).getChildAt(1).setVisibility(
						View.INVISIBLE);
				((RelativeLayout) nextChild).getChildAt(2).setVisibility(
						View.INVISIBLE);
			}

			// Set VISBLE button and border is selected
			((RelativeLayout) view).getChildAt(1).setVisibility(View.VISIBLE);
			((RelativeLayout) view).getChildAt(2).setVisibility(View.VISIBLE);

			break;
		case MotionEvent.ACTION_UP:
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			break;
		case MotionEvent.ACTION_POINTER_UP:
			break;
		case MotionEvent.ACTION_MOVE:
			RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
					.getLayoutParams();
			layoutParams.leftMargin = X - _xDelta;
			layoutParams.topMargin = Y - _yDelta;
			layoutParams.rightMargin = -100;
			layoutParams.bottomMargin = -100;
			view.setLayoutParams(layoutParams);
			break;
		}
		_root.invalidate();
		return true;
	}

	/*
	 * Override Func onPictureTaken() Rotate Image, save and merge Frame + Icon
	 * in this function
	 */

	PictureCallback pictureCallback = new PictureCallback() {

		@Override
		public void onPictureTaken(byte[] data, Camera camera) {
			// TODO Auto-generated method stub
			File pictureFileDir = getDir();

			// Check Picture File Directory
			if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {

				Log.d(CustomCameraActivity.DEBUG_TAG,
						"Can't create directory to save image.");
				Toast.makeText(getApplicationContext(),
						"Can't create directory to save image.",
						Toast.LENGTH_LONG).show();
				return;
			}

			if (data != null) {

				// Get size of Window
				Display display = getWindowManager().getDefaultDisplay();
				float width = display.getWidth();
				float height = display.getHeight();
				float scale = 900 / width;

				// Set name for Photo
				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmdd");
				String date = dateFormat.format(new Date());
				String photoName = "Picture_" + date + ".png";

				InputStream is = new ByteArrayInputStream(data);
				Bitmap bmp = BitmapFactory.decodeStream(is);

				String fileDir = getDir().toString() + "/" + photoName;

				/*
				 * Merge and save Image 1. I can't fix OutOfMemory so i scale
				 * the Image to the standard size: 900x1200 2. Coordinates of
				 * IconView what I get by getLocationInWindow() is not correct
				 * in saved Image, so must calculate coordinates again based on
				 * size of Image and scale 3. Save image and preview in
				 * 
				 * @button_img
				 */
				int nh = (int) (bmp.getHeight() * (900.0 / bmp.getWidth()));
				Bitmap scaled = Bitmap.createScaledBitmap(bmp, 900, nh, true);

				// Combine Frame
				if (saveFrame != 0) {
					Bitmap bmp1 = BitmapFactory.decodeResource(getResources(),
							saveFrame);
					Bitmap scaled1 = Bitmap.createScaledBitmap(bmp1, 900, nh,
							true);
					scaled = combineImages(scaled, scaled1, 0, 0);
				}

				/*
				 * Loop all View in ViewGroup
				 * 
				 * @param: i = 2 cause in ViewGroup @_root had 2 ChildView
				 * before
				 * 
				 * @param: locate[0] is x coordinate and locate[1] is y
				 * coordinates TAG of all IconView > 1000, call by tagArr[x -
				 * TAG]
				 */
				for (int i = 2; i < _root.getChildCount(); ++i) {
					View nextChild = _root.getChildAt(i);
					// Get Tag of IconView
					int x = (Integer) nextChild.getTag();

					if (x >= TAG) {
						// Get Location of IconView
						int[] location = new int[2];
						((RelativeLayout) nextChild).getChildAt(0)
								.getLocationInWindow(location);

						Bitmap bmp1 = BitmapFactory.decodeResource(
								getResources(), tagArr[x - TAG]);
						Bitmap iconBitmap = Bitmap.createScaledBitmap(bmp1,
								(int) (bmp1.getWidth() * scale),
								(int) (bmp1.getHeight() * scale), true);

						// Get coordinates of IconView in Image after captured
						float width1 = (location[0]) * scale;
						float height1 = (location[1] - convertDipToPixels(53))
								* scale; // TopBar height [53dip]

						// Combine image with this IconView
						scaled = combineImages(scaled, iconBitmap, width1,
								height1);
						Log.d("Location of View " + i, "" + location[0] + "/"
								+ width + "-" + location[1] + "/" + height
								+ " and " + width1 + "-" + height1);
					}
				}

				// Save Image in SDcard
				OutputStream os = null;
				try {
					Path.imageShowPath = pictureFileDir.getPath()
							+ File.separator + photoName;
					String path = pictureFileDir.getPath() + File.separator
							+ photoName;
					os = new FileOutputStream(path);
					scaled.compress(CompressFormat.PNG, 100, os);
				} catch (IOException e) {
					Log.e("SaveImage", "Problem saving image: ", e);
				}

				/*
				 * Set Image just captured for ImageButton @previewBtn
				 */
				if (fileDir != null) {
					ImageButton previewBtn = (ImageButton) findViewById(R.id.button_img);
					int size = (int) (bmp.getHeight() * (60.0 / bmp.getWidth()));
					Bitmap scaledBtn = Bitmap.createScaledBitmap(scaled, 60,
							size, true);

					if (DeviceUtils.isLGDevice()) {
						scaledBtn = ImageUtils.rotateByDegree(scaledBtn, 90);
					}
					
					previewBtn.setImageBitmap(scaledBtn);
					previewBtn.setOnClickListener(new View.OnClickListener() {

						@Override
						public void onClick(View v) {
							// ImageView mImageView;
							// mImageView =
							// (ImageView)findViewById(R.id.imageHome);
							// Bitmap image =
							// BitmapFactory.decodeFile(path.imageShowPath);
							// mImageView.setImageBitmap(image);
							Intent intent = new Intent(getApplicationContext(),
									HomeActivity.class);
							intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
							startActivity(intent);

						}
					});
				}
			}
		}
	};
	
	public Bitmap combineImages(Bitmap c, Bitmap s, float dx, float dy) {
		Bitmap cs = null;

		cs = Bitmap.createBitmap(c.getWidth(), c.getHeight(),
				Bitmap.Config.ARGB_8888);

		Canvas comboImage = new Canvas(cs);

		Matrix translateMatric = new Matrix();
		translateMatric.postTranslate(dx, dy);

		comboImage.drawBitmap(c, new Matrix(), null);
		comboImage.drawBitmap(s, translateMatric, null);

		return cs;
	}

	private File getDir() {
		File sdDir = Environment
				.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
		return new File(sdDir, "FunCamera");
	}

	@Override
	public void onPause() {

		if (camera != null) {
			camera.setPreviewCallback(null);
			preview.getHolder().removeCallback(preview);
			camera.release();
			finish();
		}
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

	@Override
	protected void onRestart() {
		// TODO Auto-generated method stub
		super.onRestart();
	}

	/*
	 * Init Preview for Camera
	 * 
	 * @frame: will addView in this FrameLayout
	 */
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		FrameLayout frame = (FrameLayout) findViewById(R.id.camera_preview);
		if (camera == null) {
			camera = getCameraInstance(currentCameraId.facing);
			preview = new CameraPreview(this, camera);
			frame.addView(preview);
		}
		super.onResume();
	}

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
	}

	public int convertDipToPixels(float dips) {
		return (int) (dips * this.getResources().getDisplayMetrics().density + 0.5f);
	}
}